package cc.zstart.utils;

import org.apache.commons.lang3.time.DateUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;


public class BeanUtil {

    /**
     * Map 转换成为Bean
     * 
     * @param map
     * @param bean
     * @return
     * @throws Exception
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<T> bean, boolean caseHump) throws Exception {
        T instance = bean.newInstance();
        Set<String> set = map.keySet();
        for (String fn : set) {
            String methodName = "set";
            if(caseHump && fn.contains("_")){
            	String[] fieldSplit = fn.split("_");
            	for (String s : fieldSplit) {
            		methodName += s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
            	}
            } else {
            	methodName += fn.substring(0, 1).toUpperCase() + fn.substring(1);
            }
    
            try {
                Field field = bean.getDeclaredField(fn);
                Method method = bean.getDeclaredMethod(methodName, field.getType());
                method.invoke(instance, typeCast(field.getType(), map.get(fn)));
            } catch (Exception e) {
                
            }
        }
        return instance;
    }
    

    public static Map<String, Object> beanToMap(Object o) {
    	return beanToMap(o, null);
    }
    public static Map<String, Object> beanToMap(Object o, Map<String, Object> targetMap) {
    	Class<? extends Object> cls = o.getClass();
    	Field[] fs = cls.getDeclaredFields();
    	if(targetMap == null){
    		targetMap = new HashMap<String, Object>();
    	}
    	for (Field f : fs) {
    		try {
    			String fn = f.getName();
    			String mn = "get" + fn.substring(0, 1).toUpperCase() + fn.substring(1);
    			Method m = cls.getMethod(mn);
    			targetMap.put(fn, m.invoke(o));
    		} catch (Exception e) {
    			throw new RuntimeException("类型转换异常");
    		}
    	}
    	return targetMap;
    }
    
    public static Map<String, Object> beanToMapExclude(Object o, String[] excludefns) {
    	return beanToMapExclude(o, null, excludefns);
    }
    public static Map<String, Object> beanToMapExclude(Object o, Map<String, Object> targetMap, String[] excludefns) {
        Class<? extends Object> cls = o.getClass();
        Field[] fs = cls.getDeclaredFields();
        List<String> listFns = ListUtil.listStr(excludefns);
        if(targetMap == null){
        	targetMap = new HashMap<String, Object>();
        }
        for (Field f : fs) {
            try {
            	String fn = f.getName();
            	if(listFns.contains(fn)){
            		continue;
            	}
                String mn = "get" + fn.substring(0, 1).toUpperCase() + fn.substring(1);
                Method m = cls.getMethod(mn);
                targetMap.put(fn, m.invoke(o));
            } catch (Exception e) {
            	throw new RuntimeException("类型转换异常");
            }
        }
        return targetMap;
    }
    
    public static Map<String, Object> beanToMapInclude(Object o, String[] includefns) {
    	return beanToMapInclude(o, null, includefns);
    }
    public static Map<String, Object> beanToMapInclude(Object o, Map<String, Object> targetMap, String[] includefns) {
    	Class<? extends Object> cls = o.getClass();
        if(targetMap == null){
        	targetMap = new HashMap<String, Object>();
        }
    	for(String fn : includefns){
    		try {
				String mn = "get" + fn.substring(0, 1).toUpperCase() + fn.substring(1);
				Method m = cls.getMethod(mn);
				if (m != null) {
					targetMap.put(fn, m.invoke(o));
				} else {
					targetMap.put(fn, null);
				}
			} catch (Exception e) {
				throw new RuntimeException("类型转换异常");
			}
    	}
    	return targetMap;
    }

	public static List<Map<String, Object>> beanListToMapList(List<?> append){
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		for(Object o : append){
			result.add(beanToMap(o));
		}
		return result;
	}
	public static List<Map<String, Object>> beanListToMapListExclude(List<?> append, String[] excludeFns){
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		for(Object o : append){
			result.add(beanToMapExclude(o, excludeFns));
		}
		return result;
	}
	public static List<Map<String, Object>> beanListToMapListInclude(List<?> append, String[] includeFns){
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		for(Object o : append){
			result.add(beanToMapInclude(o, includeFns));
		}
		return result;
	}
    
    public static boolean fkEquals(Object o1, Object o2) {
		if (o1 instanceof Number && o2 instanceof Number) { // Long <==> Integer
			return NumberUtil.numEquals((Number) o1, (Number) o2);
		}
		if (o1.getClass() != o2.getClass()) { // String <==> Integer
			return o1.toString().equals(o2.toString());
		} else {
			return o1.equals(o2);
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T typeCast(Class<T> cls, Object o) {
		try {
			if (o == null) {
				return null;
			}
			if(cls.isInstance(o)){
				return (T) o;
			}

			String ov = o.toString();
			if (cls == String.class) {
				return (T) ov;
			} else if (cls == Boolean.class) {
				return (T) Boolean.valueOf(ov);
			} else if (cls == Short.class) {
				return (T) Short.valueOf(ov);
			} else if (cls == Character.class) {
				return (T) Character.valueOf(ov.toCharArray()[0]);
			} else if (cls == Integer.class) {
				return (T) Integer.valueOf(ov);
			} else if (cls == Long.class) {
				return (T) Long.valueOf(ov);
			} else if (cls == Double.class) {
				return (T) Double.valueOf(ov);
			} else if (cls == Float.class) {
				return (T) Float.valueOf(ov);
			} else if (cls == Date.class) {
				DateUtils.parseDate(ov, "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss");
			}
		} catch (Exception e) {
			throw new RuntimeException("类型转换异常");
		}
		throw new RuntimeException("类型转换异常");
	}
}
